// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.system.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.enums.ExpertGroupEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.dao.DifficultyDao;
import com.liuxinlong.modules.dao.DifficultyPlanDao;
import com.liuxinlong.modules.dao.ExpertDao;
import com.liuxinlong.modules.dao.ExpertProjectDao;
import com.liuxinlong.modules.dao.FileManageDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.entity.Difficulty;
import com.liuxinlong.modules.entity.DifficultyPlan;
import com.liuxinlong.modules.entity.Expert;
import com.liuxinlong.modules.entity.ExpertProject;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.system.service.ExpertService;
import com.liuxinlong.modules.system.service.FileManageService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.IPUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 讲师信息业务接口层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022-12-08
 */
@Service
@Slf4j
public class ExpertServiceImpl implements ExpertService {

    @Autowired
    private ExpertDao expertDao;

    @Autowired
    private FileManageService fileManageService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private FileManageDao fileManageDao;

    @Autowired
    private ExpertProjectDao projectDao;

    @Autowired
    private DifficultyDao difficultyDao;

    @Autowired
    private DifficultyPlanDao difficultyPlanDao;

    @Override
    public List<Map<String, Object>> pageExpertInfo(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<Expert> originalList = expertDao.pageExpertInfo(queryParam);
        return completeData(originalList, startNum);
    }

    @Override
    public int getExpertInfoCount(Map<String, Object> queryParam) {
        return expertDao.getExpertInfoCount(queryParam);
    }

    @Override
    @Transactional
    public void addExpertInfo(Expert expert) {
        String id = expert.getId();
        Expert oldInfo = expertDao.selectById(id);
        if (!ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增失败，专家信息已存在！");
        }
        User expertUser = userDao.selectById(id);
        if (ObjectUtils.isEmpty(expertUser)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增失败，用户信息不存在！");
        }
        expert.setName(expertUser.getName());
        User current = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        expert.setCreateUser(current.getId());
        expertDao.insert(expert);
        fileManageService.updateBusinessFile(expert.getPicture(), id);
    }

    @Override
    @Transactional
    public void updateExpert(Expert expert) {
        String id = expert.getId();
        Expert oldInfo = expertDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，专家信息不存在！");
        }
        oldInfo.setArea(expert.getArea());
        oldInfo.setPicture(expert.getPicture());
        oldInfo.setBrief(expert.getBrief());
        User current = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        oldInfo.setUpdateUser(current.getId());
        expertDao.updateById(oldInfo);
        fileManageService.updateBusinessFile(expert.getPicture(), id);
    }

    @Override
    public void deleteExpert(String id) {
        expertDao.deleteById(id);
    }

    @Override
    public void exportExpert(HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("专家信息导出excel.xlsx");
        List<Expert> expertList = expertDao.queryExpertList(0);
        String[] head = {"序号", "姓名", "简介", "专业领域", "解决难点数", "提出风险点", "参与项目数"};
        data.setHead(head);
        String[][] dataList = new String[expertList.size()][head.length];
        int index = 0;
        for (Expert item : expertList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = item.getName();
            dataList[index][2] = item.getBrief();
            dataList[index][3] = ExpertGroupEnum.getNameByValue(Integer.parseInt(item.getArea()));
            dataList[index][4] = String.valueOf(item.getSolveNum());
            dataList[index][5] = String.valueOf(item.getRiskNum());
            dataList[index][6] = String.valueOf(item.getProjectNum());
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public void exportContribution(HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("专家贡献信息导出excel.xlsx");
        List<Expert> expertList = expertDao.queryContributionList(10000);
        String[] head = {"序号", "姓名", "简介", "专业领域", "解决难点数", "提出风险点", "参与项目数"};
        data.setHead(head);
        String[][] dataList = new String[expertList.size()][head.length];
        int index = 0;
        for (Expert item : expertList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = item.getName();
            dataList[index][2] = item.getBrief();
            dataList[index][3] = ExpertGroupEnum.getNameByValue(Integer.parseInt(item.getArea()));
            dataList[index][4] = String.valueOf(item.getSolveNum());
            dataList[index][5] = String.valueOf(item.getRiskNum());
            dataList[index][6] = String.valueOf(item.getProjectNum());
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public int syncStatisticalData() {
        // 项目
        List<ExpertProject> projectList = projectDao.getAvailableProject();
        Map<String, Integer> expertProjectMap = new HashMap<>();
        for (ExpertProject p : projectList) {
            List<String> expList = new ArrayList<>();
            List<String> divideList = Arrays.asList(p.getDivideExpert().split(","));
            List<String> appointed = Arrays.asList(p.getAppointedExpert().split(","));
            expList.addAll(divideList);
            expList.addAll(appointed);
            for (String exp : expList) {
                if (expertProjectMap.containsKey(exp)) {
                    int num = expertProjectMap.get(exp) + 1;
                    expertProjectMap.put(exp, num);
                    continue;
                }
                expertProjectMap.put(exp, 1);
            }
        }

        // 风险点
        List<Difficulty> riskList = difficultyDao.getAvailableRisk();
        Map<String, Integer> expertRiskMap = new HashMap<>();
        for (Difficulty risk : riskList) {
            List<String> expList = Arrays.asList(risk.getAssistExpert().split(","));
            for (String exp : expList) {
                if (expertRiskMap.containsKey(exp)) {
                    int num = expertRiskMap.get(exp) + 1;
                    expertRiskMap.put(exp, num);
                    continue;
                }
                expertRiskMap.put(exp, 1);
            }
        }

        // 解决难点
        List<DifficultyPlan> planList = difficultyPlanDao.getEffectiveDifficultyPlan();
        Map<String, Integer> expertPlanMap = new HashMap<>();
        Map<String, Integer> planMap = new HashMap<>();
        for (DifficultyPlan plan : planList) {
            String exp = plan.getExpertId();
            String difficulty = plan.getDifficultyId();
            String key = exp + difficulty;
            if (planMap.containsKey(key)) {
                continue;
            }
            if (expertPlanMap.containsKey(exp)) {
                int num = expertPlanMap.get(exp) + 1;
                expertPlanMap.put(exp, num);
                continue;
            }
            expertPlanMap.put(exp, 1);
        }

        List<Expert> expertList = expertDao.queryExpertList(0);
        List<Expert> newList = new ArrayList<>();
        for (Expert expert : expertList) {
            boolean modify = false;
            Expert modifyExpert = expert;
            if (expertProjectMap.containsKey(expert.getId())) {
                if (expertProjectMap.get(expert.getId()) != expert.getProjectNum()) {
                    modifyExpert.setProjectNum(expertProjectMap.get(expert.getId()));
                    modify = true;
                }
            } else {
                if (expert.getProjectNum() != 0) {
                    modifyExpert.setProjectNum(0);
                    modify = true;
                }
            }
            if (expertRiskMap.containsKey(expert.getId())) {
                if (expertRiskMap.get(expert.getId()) != expert.getRiskNum()) {
                    modifyExpert.setRiskNum(expertRiskMap.get(expert.getId()));
                    modify = true;
                }
            } else {
                if (expert.getRiskNum() != 0) {
                    modifyExpert.setRiskNum(0);
                    modify = true;
                }
            }
            if (expertPlanMap.containsKey(expert.getId())) {
                if (expertPlanMap.get(expert.getId()) != expert.getSolveNum()) {
                    modifyExpert.setSolveNum(expertPlanMap.get(expert.getId()));
                    modify = true;
                }
            } else {
                if (expert.getSolveNum() != 0) {
                    modifyExpert.setSolveNum(0);
                    modify = true;
                }
            }
            if (!modify) {
                continue;
            }
            newList.add(expert);
        }
        if (ObjectUtils.isEmpty(newList)) {
            return 0;
        }
        expertDao.updateBatchById(newList);
        return newList.size();
    }

    /**
     * 数据补全
     *
     * @param originalList 元数据
     * @param startNum     起始查询数
     * @return 补全后数据
     */
    private List<Map<String, Object>> completeData(List<Expert> originalList, int startNum) {
        if (ObjectUtils.isEmpty(originalList)) {
            return new ArrayList<>();
        }
        String currentIp = IPUtils.getCurrentIp();
        List<Map<String, Object>> resultList = new ArrayList<>(originalList.size());
        Set<String> fileIdList = originalList.stream().map(Expert::getPicture).collect(Collectors.toSet());
        Map<String, Map<String, Object>> pictureMap = fileManageDao.getFileMapByIds(fileIdList);
        int sort = startNum + 1;
        for (Expert expert : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(expert);
            item.put("sort", sort);
            item.put("areaName", ExpertGroupEnum.getNameByValue(Integer.parseInt(expert.getArea())));
            if (pictureMap.containsKey(expert.getPicture())) {
                item.put("pictureUrl", String.valueOf(pictureMap.get(expert.getPicture()).get("path")).replace("upload", "http:\\\\" + currentIp + ":8090\\preview\\upload"));
            }

            resultList.add(item);
            sort++;
        }
        return resultList;
    }
}
